#include "historypanel.h"

#include <QVBoxLayout>
#include <QToolButton>
#include <QListWidgetItem>

#include <utils/widgetutils.h>
#include <utils/pathutils.h>
#include <utils/utils.h>
#include <core/vnotex.h>
#include <core/exception.h>
#include <core/configmgr.h>
#include <core/historymgr.h>
#include <core/notebookmgr.h>
#include <core/fileopenparameters.h>

#include "titlebar.h"
#include "listwidget.h"
#include "mainwindow.h"
#include "messageboxhelper.h"

using namespace vnotex;

HistoryPanel::HistoryPanel(QWidget *p_parent)
    : QFrame(p_parent)
{
    setupUI();

    updateSeparators();
}

void HistoryPanel::setupUI()
{
    auto mainLayout = new QVBoxLayout(this);
    WidgetUtils::setContentsMargins(mainLayout);

    {
        setupTitleBar(QString(), this);
        mainLayout->addWidget(m_titleBar);
    }

    m_historyList = new ListWidget(true, this);
    m_historyList->setContextMenuPolicy(Qt::CustomContextMenu);
    m_historyList->setSelectionMode(QAbstractItemView::ExtendedSelection);
    connect(m_historyList, &QListWidget::customContextMenuRequested,
            this, &HistoryPanel::handleContextMenuRequested);
    connect(m_historyList, &QListWidget::itemActivated,
            this, &HistoryPanel::openItem);
    mainLayout->addWidget(m_historyList);

    setFocusProxy(m_historyList);
}

void HistoryPanel::setupTitleBar(const QString &p_title, QWidget *p_parent)
{
    m_titleBar = new TitleBar(p_title, false, TitleBar::Action::None, p_parent);
    m_titleBar->setActionButtonsAlwaysShown(true);

    {
        auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear"));
        connect(clearBtn, &QToolButton::triggered,
                this, &HistoryPanel::clearHistory);
    }
}

void HistoryPanel::handleContextMenuRequested(const QPoint &p_pos)
{
    auto item = m_historyList->itemAt(p_pos);
    if (!isValidItem(item)) {
        return;
    }

    QMenu menu(this);

    const int selectedCount = m_historyList->selectedItems().size();

    menu.addAction(tr("&Open"),
                   this,
                   [this]() {
                       const auto selectedItems = m_historyList->selectedItems();
                       for (const auto &selectedItem : selectedItems) {
                           openItem(selectedItem);
                       }
                   });

    if (selectedCount == 1) {
        menu.addAction(tr("&Locate Node"),
                       &menu,
                       [this]() {
                           auto item = m_historyList->currentItem();
                           if (!isValidItem(item)) {
                               return;
                           }

                           auto node = VNoteX::getInst().getNotebookMgr().loadNodeByPath(getPath(item));
                           if (node) {
                               emit VNoteX::getInst().locateNodeRequested(node.data());
                           }
                       });
    }

    menu.exec(m_historyList->mapToGlobal(p_pos));
}

void HistoryPanel::openItem(const QListWidgetItem *p_item)
{
    if (!isValidItem(p_item)) {
        return;
    }

    emit VNoteX::getInst().openFileRequested(getPath(p_item), QSharedPointer<FileOpenParameters>::create());
}

void HistoryPanel::clearHistory()
{
    int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
                                                 tr("Clear all the history?"),
                                                 QString(),
                                                 QString(),
                                                 VNoteX::getInst().getMainWindow());
    if (ret != QMessageBox::Ok) {
        return;
    }

    HistoryMgr::getInst().clear();
}

bool HistoryPanel::isValidItem(const QListWidgetItem *p_item) const
{
    return p_item && !ListWidget::isSeparatorItem(p_item);
}

void HistoryPanel::updateHistoryList()
{
    m_pendingUpdate = false;

    m_historyList->clear();

    const auto &history = HistoryMgr::getInst().getHistory();
    int itemIdx = history.size() - 1;
    for (int sepIdx = 0; sepIdx < m_separators.size() && itemIdx >= 0; ++sepIdx) {
        const auto &separator = m_separators[sepIdx];
        if (separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc) {
            // Insert this separator.
            auto sepItem = ListWidget::createSeparatorItem(separator.m_text);
            m_historyList->addItem(sepItem);

            addItem(*history[itemIdx]);
            --itemIdx;

            // Insert all qualified items.
            for (;
                 itemIdx >= 0 && separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc;
                 --itemIdx) {
                addItem(*history[itemIdx]);
            }
        }
    }

    if (itemIdx >= 0) {
        // Older.
        auto sepItem = ListWidget::createSeparatorItem(tr("Older"));
        m_historyList->addItem(sepItem);

        for (; itemIdx >= 0; --itemIdx) {
            addItem(*history[itemIdx]);
        }
    }
}

void HistoryPanel::showEvent(QShowEvent *p_event)
{
    QFrame::showEvent(p_event);

    if (!m_initialized) {
        m_initialized = true;
        connect(&HistoryMgr::getInst(), &HistoryMgr::historyUpdated,
                this, &HistoryPanel::updateHistoryListIfProper);
    }

    if (m_pendingUpdate) {
        updateHistoryList();
    }
}

void HistoryPanel::updateSeparators()
{
    m_separators.resize(3);

    // Mid-night of today.
    auto curDateTime = QDateTime::currentDateTime();
    curDateTime.setTime(QTime());

    m_separators[0].m_text = tr("Today");
    m_separators[0].m_dateUtc = curDateTime.toUTC();
    m_separators[1].m_text = tr("Yesterday");
    m_separators[1].m_dateUtc = curDateTime.addDays(-1).toUTC();
    m_separators[2].m_text = tr("Last 7 Days");
    m_separators[2].m_dateUtc = curDateTime.addDays(-7).toUTC();
}

void HistoryPanel::updateHistoryListIfProper()
{
    if (isVisible()) {
        updateHistoryList();
    } else {
        m_pendingUpdate = true;
    }
}

void HistoryPanel::addItem(const HistoryItemFull &p_hisItem)
{
    auto item = new QListWidgetItem(m_historyList);

    item->setText(PathUtils::fileNameCheap(p_hisItem.m_item.m_path));
    item->setData(Qt::UserRole, p_hisItem.m_item.m_path);
    if (p_hisItem.m_notebookName.isEmpty()) {
        item->setToolTip(tr("%1\n%2").arg(p_hisItem.m_item.m_path,
                                          Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime())));
    } else {
        item->setToolTip(tr("[%1] %2\n%3").arg(p_hisItem.m_notebookName,
                                               p_hisItem.m_item.m_path,
                                               Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime())));
    }
}

QString HistoryPanel::getPath(const QListWidgetItem *p_item) const
{
    return p_item->data(Qt::UserRole).toString();
}
